package com.jt.demo2.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;

@Component   //反射机制由spring容器管理 key：类名首小写 value：反射对象
//Aop 面向切向编程
//只是铺垫  切面 = 动态代理+方法的扩展
@org.aspectj.lang.annotation.Aspect
@Order(value = 2)
public class Aspect {
     //         切面=切入点表达式+通知方法
      @Pointcut("bean(userServiceImpl)")  //一个
     //    @Pointcut("within(com.jt.demo2.service.*)")//.*表示通配，多个
     //@Pointcut("execution(void com.jt.demo2.service.UserServiceImpl.hello())")
       // @Pointcut("@annotation(com.jt.demo2.aop.TX)")  //自定义注解
        public void pointCut(){
        }

        @Before("pointCut()")
        public void  before(JoinPoint joinPoint){
            /**
             * 连接点
             *  //通知方法 拓展(获取目标对象属性等内容)
             */
            //1.获取对象的类型
             Class targetClass =joinPoint.getTarget().getClass();
            //2.获取对象名称
            String declaringTypeName = joinPoint.getSignature().getDeclaringTypeName();
            //3.获取目标方法名称
            String name = joinPoint.getSignature().getName();
            //4.获取参数数据
            Object[] args = joinPoint.getArgs();
            System.out.println("AO入门案例 前置通知    ");
            System.out.println("目标对象类型:"+targetClass);
            System.out.println("目标对象名称:"+declaringTypeName);
            System.out.println("目标对象方法名称:"+name);
            System.out.println("目标对象方法名称:"+ Arrays.toString(args));
        }

    /**
     * 记录目标方法返回值
     *      returning 后置通知获取返回值的属性
     */
         @AfterReturning(value = "pointCut()",returning = "result")
         public void afterReturning(Object result){
            System.out.println("后置通知");
        System.out.println("方法的返回值："+result);
        }

    /**
     *  如果程序抛出异常，则有异常通知进行记录
     *         throwing：抛出异常的属性
     */
        @AfterThrowing(value = "pointCut()",throwing = "exception")
         public void afterThrowing(Exception exception){
        exception.printStackTrace();
            System.out.println("抛出出错！："+exception.getLocalizedMessage());
        }
        @After("pointCut()")  //少用
        public void after(){
            System.out.println("最终方法");
        }

        @Around("pointCut()")
        public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("环绕通知开始前2");
            Object result = joinPoint.proceed();
            System.out.println("环绕通知结束后2");
            System.out.println(result);
            return result;
        }

}
